package repo

import (
    "context"
    "device-modbus/internal/biz/dal/mysql"
    "device-modbus/internal/biz/model"
    "device-modbus/internal/biz/query"
    "time"
)

// DeviceRepo 设备数据访问接口
type DeviceRepo interface {
    Create(ctx context.Context, device *model.Device) error
    Update(ctx context.Context, device *model.Device) error
    Delete(ctx context.Context, id string) error
    GetByID(ctx context.Context, id string) (*model.Device, error)
    GetByICCID(ctx context.Context, iccid string) (*model.Device, error)
    GetByIMEI(ctx context.Context, imei string) (*model.Device, error)
    List(ctx context.Context, page, pageSize int, online, enabled *int8) ([]*model.Device, int64, error)
    UpdateOnlineStatus(ctx context.Context, id string, online int8, remoteAddr, reason string) error
}

// deviceRepo 设备数据访问实现
type deviceRepo struct {
    q *query.Query
}

func NewDeviceRepo(q *query.Query) DeviceRepo {
    return &deviceRepo{q: q}
}

func (r *deviceRepo) Create(ctx context.Context, device *model.Device) error {
    return r.q.Device.WithContext(ctx).Create(device)
}

func (r *deviceRepo) Update(ctx context.Context, device *model.Device) error {
    _, err := r.q.Device.WithContext(ctx).Where(r.q.Device.ID.Eq(device.ID)).Updates(device)
    return err
}

func (r *deviceRepo) Delete(ctx context.Context, id string) error {
    _, err := r.q.Device.WithContext(ctx).Where(r.q.Device.ID.Eq(id)).Updates(r.q.Device.IsDelete.Eq(1))
    return err
}

func (r *deviceRepo) GetByID(ctx context.Context, id string) (device *model.Device, err error) {
    err = mysql.DB.Model(&model.Device{}).WithContext(ctx).Where("id = ? AND is_delete = 0", id).First(device).Error
    return nil, err
}

func (r *deviceRepo) GetByICCID(ctx context.Context, iccid string) (device *model.Device, err error) {
    err = mysql.DB.Model(&model.Device{}).WithContext(ctx).Where("iccid = ? AND is_delete = 0", iccid).First(device).Error
    return nil, err
}

func (r *deviceRepo) GetByIMEI(ctx context.Context, imei string) (d *model.Device, err error) {
    err = mysql.DB.Model(&model.Device{}).Where("imei = ? AND is_delete = 0", imei).First(d).Error
    return nil, err
}

func (r *deviceRepo) List(ctx context.Context, page, pageSize int, online, enabled *int8) (devices []*model.Device, total int64, err error) {

    db := mysql.DB.Model(&model.Device{}).WithContext(ctx)
    query := db.WithContext(ctx).Where("is_delete=?", 0)
    if online != nil {
        query = query.Where("online=?", online)
    }
    if enabled != nil {
        query = query.Where("enabled = ?", *enabled)
    }
    err = query.Count(&total).Error
    if err != nil {
        return nil, 0, err
    }

    offset := (page - 1) * pageSize
    query.Order("ctime DESC").Offset(offset).Limit(pageSize).Find(&devices)
    return devices, total, err
}

func (r *deviceRepo) UpdateOnlineStatus(ctx context.Context, id string, online int8, remoteAddr, reason string) error {
    now := time.Now()
    _, err := r.q.Device.WithContext(ctx).
        Where(r.q.Device.ID.Eq(id)).
        Updates(map[string]interface{}{
            "online":         online,
            "remote_addr":    remoteAddr,
            "offline_reason": reason,
            "last_time":      now,
            "utime":          now,
        })
    return err
}
